// 《围棋》作者版权所有。版权所有。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// go:build ignore 
// +build ignore 

package main

import "strings"

// /注意：
// -整数类型位于寄存器的低部分。上部是垃圾。
// /-布尔类型使用寄存器的低位字节。0=假，1=真。
// 高位字节是垃圾。
// /-*常量指令可能使用大于指令编码的常数。
// 在这种情况下，汇编程序扩展到多条指令，并使用tmp 
// 寄存器（R11）。

// 后缀对各种指令的位宽度进行编码。
// W（字）=32位
// H（半字）=16位
// HU=16位无符号
// B（字节）=8位
// BU 8位无符号
// F（浮点）=32位浮点
// D（双）=64位浮点

var regNamesARM = []string{
	"R0",
	"R1",
	"R2",
	"R3",
	"R4",
	"R5",
	"R6",
	"R7",
	"R8",
	"R9",
	"g",   // R10 
	"R11", // tmp 
	"R12",
	"R14", // link 
	"R15", // pc 

	"F0",
	"F1",
	"F2",
	"F3",
	"F4",
	"F5",
	"F6",
	"F7",
	"F8",
	"F9",
	"F10",
	"F11",
	"F12",
	"F13",
	"F14",
	"F15", // tmp 

	// 如果添加寄存器，请在运行时更新asyncPreempt。

	// 伪寄存器
	"SB",
}

func init() {
	// 将注册表名映射到注册表整数。
	if len(regNamesARM) > 64 {
		panic("too many registers")
	}
	num := map[string]int{}
	for i, name := range regNamesARM {
		num[name] = i
	}
	buildReg := func(s string) regMask {
		m := regMask(0)
		for _, r := range strings.Split(s, " ") {
			if n, ok := num[r]; ok {
				m |= regMask(1) << uint(n)
				continue
			}
			panic("register " + r + " not found")
		}
		return m
	}

	// 通用单个寄存器掩码
	var (
		gp         = buildReg("R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14")
		gpg        = gp | buildReg("g")
		gpsp       = gp | buildReg("SP")
		gpspg      = gpg | buildReg("SP")
		gpspsbg    = gpspg | buildReg("SB")
		fp         = buildReg("F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15")
		callerSave = gp | fp | buildReg("g") // 运行时。setg（以及任何称之为setg的东西）可能会破坏g 
		r0         = buildReg("R0")
		r1         = buildReg("R1")
		r2         = buildReg("R2")
		r3         = buildReg("R3")
		r4         = buildReg("R4")
	)
	// 公共区域
	var (
		gp01      = regInfo{inputs: nil, outputs: []regMask{gp}}
		gp11      = regInfo{inputs: []regMask{gpg}, outputs: []regMask{gp}}
		gp11carry = regInfo{inputs: []regMask{gpg}, outputs: []regMask{gp, 0}}
		gp11sp    = regInfo{inputs: []regMask{gpspg}, outputs: []regMask{gp}}
		gp1flags  = regInfo{inputs: []regMask{gpg}}
		gp1flags1 = regInfo{inputs: []regMask{gp}, outputs: []regMask{gp}}
		gp21      = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{gp}}
		gp21carry = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{gp, 0}}
		gp2flags  = regInfo{inputs: []regMask{gpg, gpg}}
		gp2flags1 = regInfo{inputs: []regMask{gp, gp}, outputs: []regMask{gp}}
		gp22      = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{gp, gp}}
		gp31      = regInfo{inputs: []regMask{gp, gp, gp}, outputs: []regMask{gp}}
		gp31carry = regInfo{inputs: []regMask{gp, gp, gp}, outputs: []regMask{gp, 0}}
		gp3flags  = regInfo{inputs: []regMask{gp, gp, gp}}
		gp3flags1 = regInfo{inputs: []regMask{gp, gp, gp}, outputs: []regMask{gp}}
		gpload    = regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{gp}}
		gpstore   = regInfo{inputs: []regMask{gpspsbg, gpg}}
		gp2load   = regInfo{inputs: []regMask{gpspsbg, gpg}, outputs: []regMask{gp}}
		gp2store  = regInfo{inputs: []regMask{gpspsbg, gpg, gpg}}
		fp01      = regInfo{inputs: nil, outputs: []regMask{fp}}
		fp11      = regInfo{inputs: []regMask{fp}, outputs: []regMask{fp}}
		fp1flags  = regInfo{inputs: []regMask{fp}}
		fpgp      = regInfo{inputs: []regMask{fp}, outputs: []regMask{gp}, clobbers: buildReg("F15")} // 整数浮点转换使用F15作为tmp 
		gpfp      = regInfo{inputs: []regMask{gp}, outputs: []regMask{fp}, clobbers: buildReg("F15")}
		fp21      = regInfo{inputs: []regMask{fp, fp}, outputs: []regMask{fp}}
		fp31      = regInfo{inputs: []regMask{fp, fp, fp}, outputs: []regMask{fp}}
		fp2flags  = regInfo{inputs: []regMask{fp, fp}}
		fpload    = regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{fp}}
		fpstore   = regInfo{inputs: []regMask{gpspsbg, fp}}
		readflags = regInfo{inputs: nil, outputs: []regMask{gp}}
	)
	ops := []opData{
		// 二进制运算
		{name: "ADD", argLength: 2, reg: gp21, asm: "ADD", commutative: true},     // arg0+arg1 
		{name: "ADDconst", argLength: 1, reg: gp11sp, asm: "ADD", aux: "Int32"},   // arg0+auxInt 
		{name: "SUB", argLength: 2, reg: gp21, asm: "SUB"},                        // arg0-arg1 
		{name: "SUBconst", argLength: 1, reg: gp11, asm: "SUB", aux: "Int32"},     // arg0-auxInt 
		{name: "RSB", argLength: 2, reg: gp21, asm: "RSB"},                        // arg1-arg0 
		{name: "HMUL", argLength: 2, reg: gp21, asm: "MULL", commutative: true},   // （arg0*arg1）>>32，有符号
		{name: "HMULU", argLength: 2, reg: gp21, asm: "MULLU", commutative: true}, // （arg0*arg1）>>32，无符号

		// udiv运行时调用软除法
		// output0=arg0/arg1，output1=arg0%arg1-
		{
			name:      "CALLudiv",
			argLength: 2,
			reg: regInfo{
				inputs:   []regMask{buildReg("R1"), buildReg("R0")},
				outputs:  []regMask{buildReg("R0"), buildReg("R1")},
				clobbers: buildReg("R2 R3 R12 R14"), // R14是LR，R12是链接器蹦床划痕寄存器
			},
			clobberFlags: true,
			typ:          "(UInt32,UInt32)",
			call:         false, // TODO（mdempsky）：这是真的吗？
		},

		{name: "ADDS", argLength: 2, reg: gp21carry, asm: "ADD", commutative: true}, // arg0+arg1，设置进位标志
		{name: "ADDSconst", argLength: 1, reg: gp11carry, asm: "ADD", aux: "Int32"}, // arg0+auxInt，设置进位标志
		{name: "ADC", argLength: 3, reg: gp2flags1, asm: "ADC", commutative: true},  // arg0+arg1+carry，arg2=标志
		{name: "ADCconst", argLength: 2, reg: gp1flags1, asm: "ADC", aux: "Int32"},  // arg0+auxInt+carry，arg1=标志
		{name: "SBC", argLength: 3, reg: gp2flags1, asm: "SBC"},                     // arg0-arg1-carry，arg2=标志
		{name: "SBCconst", argLength: 2, reg: gp1flags1, asm: "SBC", aux: "Int32"},  // arg0-auxInt-carry，arg1=标志
		{name: "RSCconst", argLength: 2, reg: gp1flags1, asm: "RSC", aux: "Int32"},  // auxInt-arg0-carry，arg1=标志

		{name: "MULLU", argLength: 2, reg: gp22, asm: "MULLU", commutative: true}, // arg0*arg1，输出高32位，输出端32位低位
		{name: "MULA", argLength: 3, reg: gp31, asm: "MULA"},                      // arg0*arg1+arg2 
		{name: "MULS", argLength: 3, reg: gp31, asm: "MULS"},                      // arg2-arg0*arg1 

		{name: "ADDF", argLength: 2, reg: fp21, asm: "ADDF", commutative: true},   // arg0+arg1 
		{name: "ADDD", argLength: 2, reg: fp21, asm: "ADDD", commutative: true},   // arg0+arg1 
		{name: "SUBF", argLength: 2, reg: fp21, asm: "SUBF"},                      // arg0-arg1 
		{name: "SUBD", argLength: 2, reg: fp21, asm: "SUBD"},                      // arg0-arg1 
		{name: "MULF", argLength: 2, reg: fp21, asm: "MULF", commutative: true},   // 190
		{name: "DIVD", argLength: 2, reg: fp21, asm: "DIVD"},                      // arg0/arg1 

		{name: "MULAF", argLength: 3, reg: fp31, asm: "MULAF", resultInArg0: true}, // arg0+（arg1*arg2）
		{name: "MULAD", argLength: 3, reg: fp31, asm: "MULAD", resultInArg0: true}, // arg0+（arg1*arg2）
		{name: "MULSF", argLength: 3, reg: fp31, asm: "MULSF", resultInArg0: true}, // arg0-（arg1*arg2）
		{name: "MULSD", argLength: 3, reg: fp31, asm: "MULSD", resultInArg0: true}, // arg0-（arg1*arg2）

		// FMULAD仅存在于具有VF4指令集的平台上。
		// 任何使用之前都必须成功检查运行时。手臂支撑vfpv4。
		{name: "FMULAD", argLength: 3, reg: fp31, asm: "FMULAD", resultInArg0: true}, // arg0+（arg1*arg2）

		{name: "AND", argLength: 2, reg: gp21, asm: "AND", commutative: true}, // arg0和arg1 
		{name: "ANDconst", argLength: 1, reg: gp11, asm: "AND", aux: "Int32"}, // arg0和生长素
		{name: "OR", argLength: 2, reg: gp21, asm: "ORR", commutative: true},  // arg0 | arg1 
		{name: "ORconst", argLength: 1, reg: gp11, asm: "ORR", aux: "Int32"},  // arg0 |生长素
		{name: "XOR", argLength: 2, reg: gp21, asm: "EOR", commutative: true}, // arg0^arg1 
		{name: "BIC", argLength: 2, reg: gp21, asm: "BIC"},                    // arg0和arg1 

		{name: "BFX", argLength: 1, reg: gp11, asm: "BFX", aux: "Int32"},   // 从arg0中的位L中提取W位，然后有符号扩展
		{name: "BFXU", argLength: 1, reg: gp11, asm: "BFXU", aux: "Int32"}, // 从arg0中的位L中提取W位，然后无符号扩展

		// 一元运算
		{name: "MVN", argLength: 1, reg: gp11, asm: "MVN"}, // /^arg0 

		{name: "NEGD", argLength: 1, reg: fp11, asm: "NEGD"},   // /-arg0，float64 
		{name: "ABSD", argLength: 1, reg: fp11, asm: "ABSD"},   // abs（arg0），float64 

		{name: "CLZ", argLength: 1, reg: gp11, asm: "CLZ"},     // count leading zero 
		{name: "REV", argLength: 1, reg: gp11, asm: "REV"},     // reverse byte order 
		{name: "REV16", argLength: 1, reg: gp11, asm: "REV16"}, // reverse byte order 16位半字
		{name: "RBIT", argLength: 1, reg: gp11, asm: "RBIT"},   // reverse bit order 

		// shift 
		{name: "SLL", argLength: 2, reg: gp21, asm: "SLL"},                    // arg0<<arg1，移位量为mod 256 
		{name: "SRL", argLength: 2, reg: gp21, asm: "SRL"},                    // arg0>>arg1，无符号，移位量为mod 256 
		{name: "SRLconst", argLength: 1, reg: gp11, asm: "SRL", aux: "Int32"}, // arg0>>生长素，无符号，0<=生长素<32 
		{name: "SRA", argLength: 2, reg: gp21, asm: "SRA"},                    // arg0>>arg1，有符号，移位量为mod 256 
		{name: "SRAconst", argLength: 1, reg: gp11, asm: "SRA", aux: "Int32"}, // arg0>>生长素，有符号，0<=生长素<32 
		{name: "SRR", argLength: 2, reg: gp21},                                // arg0按arg1位右转
		{name: "SRRconst", argLength: 1, reg: gp11, aux: "Int32"},             // arg0按生长素位右转，0<=auxInt<32 

		// auxInt对于所有这些满足0<=auxInt<32 
		{name: "ADDshiftLL", argLength: 2, reg: gp21, asm: "ADD", aux: "Int32"}, // arg0+arg1<<auxInt 
		{name: "ADDshiftRL", argLength: 2, reg: gp21, asm: "ADD", aux: "Int32"}, // arg0+arg1>>auxInt，无符号移位
		{name: "ADDshiftRA", argLength: 2, reg: gp21, asm: "ADD", aux: "Int32"}, // arg0+arg1>>auxInt，符号移位
		{name: "SUBshiftLL", argLength: 2, reg: gp21, asm: "SUB", aux: "Int32"}, // arg0-arg1</auxInt 
		{name: "RSBshiftLL", argLength: 2, reg: gp21, asm: "RSB", aux: "Int32"}, // arg1<<生长素-arg0 
		{name: "RSBshiftRL", argLength: 2, reg: gp21, asm: "RSB", aux: "Int32"}, // arg1>>生长素-arg0，无符号移位
		{name: "RSBshiftRA", argLength: 2, reg: gp21, asm: "RSB", aux: "Int32"}, // arg1>>生长素-arg0，有符号移位
		{name: "ANDshiftLL", argLength: 2, reg: gp21, asm: "AND", aux: "Int32"}, // arg0&（arg1<<auxInt）
		{name: "ANDshiftRL", argLength: 2, reg: gp21, asm: "AND", aux: "Int32"}, // arg0&（arg1>>生长素），无符号移位
		{name: "ANDshiftRA", argLength: 2, reg: gp21, asm: "AND", aux: "Int32"}, // arg0&（arg1>>生长素），有符号移位
		{name: "ORshiftLL", argLength: 2, reg: gp21, asm: "ORR", aux: "Int32"},  // arg0 | arg1<<生长素
		{name: "ORshiftRL", argLength: 2, reg: gp21, asm: "ORR", aux: "Int32"},  // arg0 | arg1>>生长素，无符号移位
		{name: "ORshiftRA", argLength: 2, reg: gp21, asm: "ORR", aux: "Int32"},  // arg0 | arg1>>生长素，有符号移位
		{name: "XORshiftLL", argLength: 2, reg: gp21, asm: "EOR", aux: "Int32"}, // arg0^arg1<<生长素
		{name: "XORshiftRR", argLength: 2, reg: gp21, asm: "EOR", aux: "Int32"}, // arg0^（arg1由生长素右转）
		{name: "BICshiftLL", argLength: 2, reg: gp21, asm: "BIC", aux: "Int32"}, // arg0&^（arg1<<生长素）
		{name: "BICshiftRL", argLength: 2, reg: gp21, asm: "BIC", aux: "Int32"}, // arg0&^（arg1>>生长素），无符号移位
		{name: "BICshiftRA", argLength: 2, reg: gp21, asm: "BIC", aux: "Int32"}, // arg0&^（arg1>>生长素），有符号移位

		{name: "ADCshiftLL", argLength: 3, reg: gp2flags1, asm: "ADC", aux: "Int32"}, // arg0+arg1<生长素+进位，arg2=标志
		{name: "ADCshiftRL", argLength: 3, reg: gp2flags1, asm: "ADC", aux: "Int32"}, // arg0+arg1>>生长素+进位，无符号移位，arg2=标志
		{name: "ADCshiftRA", argLength: 3, reg: gp2flags1, asm: "ADC", aux: "Int32"}, // arg0+arg1>>生长素+进位，有符号移位，arg2=标志
		{name: "SBCshiftLL", argLength: 3, reg: gp2flags1, asm: "SBC", aux: "Int32"}, // arg0-arg1<生长素-进位，arg2=标志
		{name: "SBCshiftRL", argLength: 3, reg: gp2flags1, asm: "SBC", aux: "Int32"}, // arg0-arg1>>生长素-进位，无符号移位，arg2=flags 
		{name: "SBCshiftRA", argLength: 3, reg: gp2flags1, asm: "SBC", aux: "Int32"}, // arg0-arg1>>auxInt-carry，signed shift，arg2=flags 
		{name: "RSCshiftLL", argLength: 3, reg: gp2flags1, asm: "RSC", aux: "Int32"}, // arg1<auxInt-arg0-carry，arg2=flags 
		{name: "RSCshiftRL", argLength: 3, reg: gp2flags1, asm: "RSC", aux: "Int32"}, // arg1>>auxInt-arg0-carry，unsigned shift，arg2=flags 
		{name: "RSCshiftRA", argLength: 3, reg: gp2flags1, asm: "RSC", aux: "Int32"}, // arg1>>auxInt-arg0-carry，signed shift，arg2=flags 

		{name: "ADDSshiftRL", argLength: 2, reg: gp21carry, asm: "ADD", aux: "Int32"}, // arg0+arg1>>生长素，无符号移位，设置进位标志
		{name: "ADDSshiftRA", argLength: 2, reg: gp21carry, asm: "ADD", aux: "Int32"}, // arg0+arg1>>生长素，有符号移位，设置进位标志
		{name: "SUBSshiftLL", argLength: 2, reg: gp21carry, asm: "SUB", aux: "Int32"}, // arg0-arg1<<auxInt，设置进位标志
		{name: "SUBSshiftRL", argLength: 2, reg: gp21carry, asm: "SUB", aux: "Int32"}, // arg0-arg1>>生长素，无符号移位，设置进位标志
		{name: "RSBSshiftLL", argLength: 2, reg: gp21carry, asm: "RSB", aux: "Int32"}, // arg1<<生长素-arg0，设置进位标志
		{name: "RSBSshiftRL", argLength: 2, reg: gp21carry, asm: "RSB", aux: "Int32"}, // arg1>>生长素-arg0，无符号移位，设置进位标志
		{name: "RSBSshiftRA", argLength: 2, reg: gp21carry, asm: "RSB", aux: "Int32"}, // arg1>>生长素-arg0，有符号移位，设置进位标志

		{name: "ADDshiftLLreg", argLength: 3, reg: gp31, asm: "ADD"}, // arg0+arg1<<arg2 
		{name: "SUBshiftLLreg", argLength: 3, reg: gp31, asm: "SUB"}, // arg0-arg1<<arg2-
		{name: "SUBshiftRLreg", argLength: 3, reg: gp31, asm: "SUB"}, // arg0-arg1>>arg2，无符号移位
		{name: "SUBshiftRAreg", argLength: 3, reg: gp31, asm: "SUB"}, // arg0-arg1>>arg2，有符号移位
		{name: "RSBshiftLLreg", argLength: 3, reg: gp31, asm: "RSB"}, // arg1<<arg2-arg0-
		{name: "ANDshiftRAreg", argLength: 3, reg: gp31, asm: "AND"}, // arg0&（arg1>>arg2），有符号移位
		{name: "ORshiftLLreg", argLength: 3, reg: gp31, asm: "ORR"},  // arg0 | arg1<<arg2 
		{name: "ORshiftRLreg", argLength: 3, reg: gp31, asm: "ORR"},  // arg0 | arg1>>arg2，无符号移位
		{name: "ORshiftRAreg", argLength: 3, reg: gp31, asm: "ORR"},  // arg0 | arg1>>arg2，带符号移位
		{name: "BICshiftLLreg", argLength: 3, reg: gp31, asm: "BIC"}, // arg0&^（arg1<<arg2）
		{name: "BICshiftRLreg", argLength: 3, reg: gp31, asm: "BIC"}, // arg0&^（arg1>>arg2），带符号移位
		{name: "BICshiftRAreg", argLength: 3, reg: gp31, asm: "BIC"}, // arg0&^（arg1>>arg2），带符号移位
		{name: "MVNshiftLLreg", argLength: 2, reg: gp21, asm: "MVN"}, // ^（arg0<<arg1）

		{name: "ADCshiftRLreg", argLength: 4, reg: gp3flags1, asm: "ADC"}, // arg0+arg1>>arg2+进位，无符号移位，arg3=标志
		{name: "ADCshiftRAreg", argLength: 4, reg: gp3flags1, asm: "ADC"}, // arg0+arg1>>arg2+进位，有符号移位，arg3=标志
		{name: "SBCshiftLLreg", argLength: 4, reg: gp3flags1, asm: "SBC"}, // arg0-arg1<<arg2-进位，arg3=标志
		{name: "SBCshiftRLreg", argLength: 4, reg: gp3flags1, asm: "SBC"}, // arg0-arg1>>arg2-进位，无符号移位，arg3=标志
		{name: "SBCshiftRAreg", argLength: 4, reg: gp3flags1, asm: "SBC"}, // arg0-arg1>>有符号移位，arg3=标志
		{name: "RSCshiftLLreg", argLength: 4, reg: gp3flags1, asm: "RSC"}, // arg1<<arg2-arg0-进位，arg3=标志
		{name: "RSCshiftRLreg", argLength: 4, reg: gp3flags1, asm: "RSC"}, // arg1>>arg2-arg0-进位，无符号移位，arg3=标志
		{name: "RSCshiftRAreg", argLength: 4, reg: gp3flags1, asm: "RSC"}, // arg1>>arg2-arg0-进位，有符号移位，arg3=标志

		{name: "ADDSshiftLLreg", argLength: 3, reg: gp31carry, asm: "ADD"}, // arg0+arg1<<arg2，设置进位标志
		{name: "SUBSshiftLLreg", argLength: 3, reg: gp31carry, asm: "SUB"}, // arg0-arg1<<arg2，设置进位标志
		{name: "SUBSshiftRLreg", argLength: 3, reg: gp31carry, asm: "SUB"}, // arg0-arg1>>arg2，无符号移位，设置进位标志
		{name: "SUBSshiftRAreg", argLength: 3, reg: gp31carry, asm: "SUB"}, // arg0-arg1>>arg2，有符号移位，设置进位标志
		{name: "RSBSshiftLLreg", argLength: 3, reg: gp31carry, asm: "RSB"}, // arg1<<arg2-arg0，设置进位标志
		{name: "RSBSshiftRLreg", argLength: 3, reg: gp31carry, asm: "RSB"}, // arg1>>arg2-arg0，无符号移位，设置进位标志

		// 比较
		{name: "CMP", argLength: 2, reg: gp2flags, asm: "CMP", typ: "Flags"},                    // arg0比较到arg1 
		{name: "CMPconst", argLength: 1, reg: gp1flags, asm: "CMP", aux: "Int32", typ: "Flags"}, // arg0比较到生长素
		{name: "CMN", argLength: 2, reg: gp2flags, asm: "CMN", typ: "Flags", commutative: true}, // arg0比较到-arg1，如果arg1不是1<<63 
		{name: "CMNconst", argLength: 1, reg: gp1flags, asm: "CMN", aux: "Int32", typ: "Flags"}, // arg0与-auxInt 
		{name: "TST", argLength: 2, reg: gp2flags, asm: "TST", typ: "Flags", commutative: true}, // arg0和arg1与0 
		{name: "TSTconst", argLength: 1, reg: gp1flags, asm: "TST", aux: "Int32", typ: "Flags"}, // arg0和auxInt与0 
		{name: "TEQ", argLength: 2, reg: gp2flags, asm: "TEQ", typ: "Flags", commutative: true}, // arg0^arg1与0 
		{name: "TEQconst", argLength: 1, reg: gp1flags, asm: "TEQ", aux: "Int32", typ: "Flags"}, // arg0^auxInt与0 
		{name: "CMPF", argLength: 2, reg: fp2flags, asm: "CMPF", typ: "Flags"},                  // arg0与arg1比较，32 
		{name: "CMPD", argLength: 2, reg: fp2flags, asm: "CMPD", typ: "Flags"},                  // arg0与arg1比较，float64 

		{name: "CMPshiftLL", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int32", typ: "Flags"}, // arg0与arg1比较<<生长素
		{name: "CMPshiftRL", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int32", typ: "Flags"}, // arg0与arg1比较
		{name: "CMPshiftRA", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int32", typ: "Flags"}, // arg0与arg1比较>>生长素，有符号移位
		{name: "CMNshiftLL", argLength: 2, reg: gp2flags, asm: "CMN", aux: "Int32", typ: "Flags"}, // arg0与-（arg1<<生长素）
		{name: "TSTshiftLL", argLength: 2, reg: gp2flags, asm: "TST", aux: "Int32", typ: "Flags"}, // arg0&（arg1<<auxInt）与0相比
		{name: "TSTshiftRL", argLength: 2, reg: gp2flags, asm: "TST", aux: "Int32", typ: "Flags"}, // arg0&（arg1>>auxInt）与0相比，无符号移位
		{name: "TSTshiftRA", argLength: 2, reg: gp2flags, asm: "TST", aux: "Int32", typ: "Flags"}, // arg0&（arg1>>auxInt）与0相比，有符号移位
		{name: "TEQshiftLL", argLength: 2, reg: gp2flags, asm: "TEQ", aux: "Int32", typ: "Flags"}, // arg0^（arg1<<auxInt）与0相比，无符号移位
		{name: "TEQshiftRA", argLength: 2, reg: gp2flags, asm: "TEQ", aux: "Int32", typ: "Flags"}, // arg0^（arg1>>生长素）与0比较，有符号移位

		{name: "CMPshiftLLreg", argLength: 3, reg: gp3flags, asm: "CMP", typ: "Flags"}, // arg0与arg1比较<<arg2 
		{name: "CMPshiftRLreg", argLength: 3, reg: gp3flags, asm: "CMP", typ: "Flags"}, // arg0与arg1>>arg2，无符号移位
		{name: "CMPshiftRAreg", argLength: 3, reg: gp3flags, asm: "CMP", typ: "Flags"}, // arg0与arg1>>arg2比较，有符号移位
		{name: "CMNshiftRAreg", argLength: 3, reg: gp3flags, asm: "CMN", typ: "Flags"}, // arg0+（arg1>>arg2）与0比较，有符号移位
		{name: "TSTshiftLLreg", argLength: 3, reg: gp3flags, asm: "TST", typ: "Flags"}, // arg0&（arg1<<arg2）与0比较
		{name: "TSTshiftRLreg", argLength: 3, reg: gp3flags, asm: "TST", typ: "Flags"}, // arg0&（arg1>>arg2）与0比较，无符号移位
		{name: "TEQshiftRAreg", argLength: 3, reg: gp3flags, asm: "TEQ", typ: "Flags"}, // arg0^（arg1>>arg2）与0比较，有符号移位

		{name: "CMPF0", argLength: 1, reg: fp1flags, asm: "CMPF", typ: "Flags"}, // arg0与0比较，float32 
		{name: "CMPD0", argLength: 1, reg: fp1flags, asm: "CMPD", typ: "Flags"}, // arg0与0比较，float64 

		// ，将32位浮点
		{name: "MOVDconst", argLength: 0, reg: fp01, aux: "Float64", asm: "MOVD", typ: "Float64", rematerializeable: true}, // auxint转换为64位浮点

		{name: "MOVWaddr", argLength: 1, reg: regInfo{inputs: []regMask{buildReg("SP") | buildReg("SB")}, outputs: []regMask{gp}}, aux: "SymOff", asm: "MOVW", rematerializeable: true, symEffect: "Addr"}, // arg0+auxint+aux。（*gc.Sym），arg0=SP/SB 

		{name: "MOVBload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVB", typ: "Int8", faultOnNilArg0: true, symEffect: "Read"},     // 从arg0+auxInt+aux加载。arg1=mem。
		{name: "MOVBUload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVBU", typ: "UInt8", faultOnNilArg0: true, symEffect: "Read"},  // 从arg0+生长素+辅助加载。arg1=mem。
		{name: "MOVHload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVH", typ: "Int16", faultOnNilArg0: true, symEffect: "Read"},    // 从arg0+auxInt+aux加载。arg1=mem。
		{name: "MOVHUload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVHU", typ: "UInt16", faultOnNilArg0: true, symEffect: "Read"}, // 从arg0+auxInt+aux加载。arg1=mem。
		{name: "MOVWload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVW", typ: "UInt32", faultOnNilArg0: true, symEffect: "Read"},   // 从arg0+auxInt+aux加载。arg1=mem。
		{name: "MOVFload", argLength: 2, reg: fpload, aux: "SymOff", asm: "MOVF", typ: "Float32", faultOnNilArg0: true, symEffect: "Read"},  // 从arg0+auxInt+aux加载。arg1=mem。
		{name: "MOVDload", argLength: 2, reg: fpload, aux: "SymOff", asm: "MOVD", typ: "Float64", faultOnNilArg0: true, symEffect: "Read"},  // 从arg0+auxInt+aux加载。arg1=mem。

		{name: "MOVBstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVB", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将arg1的1字节存储到arg0+auxInt+aux。arg2=mem。
		{name: "MOVHstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVH", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将arg1的2字节存储到arg0+auxInt+aux。arg2=mem。
		{name: "MOVWstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVW", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将arg1的4字节存储到arg0+auxInt+aux。arg2=mem。
		{name: "MOVFstore", argLength: 3, reg: fpstore, aux: "SymOff", asm: "MOVF", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将4字节的arg1存储到arg0+auxInt+aux。arg2=mem。
		{name: "MOVDstore", argLength: 3, reg: fpstore, aux: "SymOff", asm: "MOVD", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将8字节的arg1存储到arg0+auxInt+aux。arg2=mem。

		{name: "MOVWloadidx", argLength: 3, reg: gp2load, asm: "MOVW", typ: "UInt32"},                   // 从arg0+arg1加载。arg2=mem 
		{name: "MOVWloadshiftLL", argLength: 3, reg: gp2load, asm: "MOVW", aux: "Int32", typ: "UInt32"}, // 从arg0+arg1加载。arg2=mem 
		{name: "MOVWloadshiftRL", argLength: 3, reg: gp2load, asm: "MOVW", aux: "Int32", typ: "UInt32"}, // 从arg0+arg1加载>>生长素，无符号移位。arg2=mem 
		{name: "MOVWloadshiftRA", argLength: 3, reg: gp2load, asm: "MOVW", aux: "Int32", typ: "UInt32"}, // 从arg0+arg1加载>>生长素，带符号移位。arg2=mem 
		{name: "MOVBUloadidx", argLength: 3, reg: gp2load, asm: "MOVBU", typ: "UInt8"},                  // 从arg0+arg1加载。arg2=mem 
		{name: "MOVBloadidx", argLength: 3, reg: gp2load, asm: "MOVB", typ: "Int8"},                     // 从arg0+arg1加载。arg2=mem 
		{name: "MOVHUloadidx", argLength: 3, reg: gp2load, asm: "MOVHU", typ: "UInt16"},                 // 从arg0+arg1加载。arg2=mem 
		{name: "MOVHloadidx", argLength: 3, reg: gp2load, asm: "MOVH", typ: "Int16"},                    // 从arg0+arg1加载。arg2=mem 

		{name: "MOVWstoreidx", argLength: 4, reg: gp2store, asm: "MOVW", typ: "Mem"},                   // 将arg2存储到arg0+arg1。arg3=mem 
		{name: "MOVWstoreshiftLL", argLength: 4, reg: gp2store, asm: "MOVW", aux: "Int32", typ: "Mem"}, // 将arg2存储到arg0+arg1<<生长素。arg3=mem 
		{name: "MOVWstoreshiftRL", argLength: 4, reg: gp2store, asm: "MOVW", aux: "Int32", typ: "Mem"}, // 将arg2存储到arg0+arg1>>生长素，无符号移位。arg3=mem 
		{name: "MOVWstoreshiftRA", argLength: 4, reg: gp2store, asm: "MOVW", aux: "Int32", typ: "Mem"}, // 将arg2存储到arg0+arg1>>生长素，带符号移位。arg3=mem 
		{name: "MOVBstoreidx", argLength: 4, reg: gp2store, asm: "MOVB", typ: "Mem"},                   // 将arg2存储到arg0+arg1。arg3=mem 
		{name: "MOVHstoreidx", argLength: 4, reg: gp2store, asm: "MOVH", typ: "Mem"},                   // 将arg2存储到arg0+arg1。arg3=mem 

		{name: "MOVBreg", argLength: 1, reg: gp11, asm: "MOVBS"},  // 从arg0开始移动，从字节


		{name: "MOVWF", argLength: 1, reg: gpfp, asm: "MOVWF"},  // int32->float32 
		{name: "MOVWD", argLength: 1, reg: gpfp, asm: "MOVWD"},  // int32->float64 
		{name: "MOVWUF", argLength: 1, reg: gpfp, asm: "MOVWF"}, // uint32->float32，在指令
		{name: "MOVWUD", argLength: 1, reg: gpfp, asm: "MOVWD"}, // uint32->float64中设置U位，在指令
		{name: "MOVFW", argLength: 1, reg: fpgp, asm: "MOVFW"},  // float32->int32 
		{name: "MOVDW", argLength: 1, reg: fpgp, asm: "MOVDW"},  // float64->int32 
		{name: "MOVFWU", argLength: 1, reg: fpgp, asm: "MOVFW"}, // float32->uint32，在指令
		{name: "MOVDWU", argLength: 1, reg: fpgp, asm: "MOVDW"}, // float64->uint32中设置U位，在指令
		{name: "MOVFD", argLength: 1, reg: fp11, asm: "MOVFD"},  // float32->float64 
		{name: "MOVDF", argLength: 1, reg: fp11, asm: "MOVDF"},  // float64->float32 

		// 条件指令中设置U位，用于降低移位
		{name: "CMOVWHSconst", argLength: 2, reg: gp1flags1, asm: "MOVW", aux: "Int32", resultInArg0: true}, // 如果标志指示HS，则替换arg0 w/const；如果标志指示LS，则替换arg0 w/const；如果标志指示LS，则替换arg0 w/const；如果标志指示HS，则替换arg1=标志
		{name: "SRAcond", argLength: 3, reg: gp2flags1, asm: "SRA"},                                         // 如果标志指示HS，则替换arg0>>arg1；否则，则替换arg2=标志

		// 函数调用
		{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true},                                              // 调用静态函数aux。（*obj.LSym）。arg0=mem，auxint=argsize，返回mem 
		{name: "CALLtail", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true, tailCall: true},                                // tail call static function aux。（*obj.LSym）。arg0=mem，auxint=argsize，返回mem 
		{name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R7"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // 通过闭包调用函数。arg0=codeptr，arg1=closure，arg2=mem，auxint=argsize，返回mem 
		{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true},                        // 通过指针调用fn。arg0=codeptr，arg1=mem，auxint=argsize，返回mem 

		// pseudo ops 
		{name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpg}}, nilCheck: true, faultOnNilArg0: true}, // arg0为零时惊慌。arg1=mem。

		{name: "Equal", argLength: 1, reg: readflags},         // bool，true标志编码x==y，否则为false。
		{name: "NotEqual", argLength: 1, reg: readflags},      // bool，真标志编码x=否则就错了。
		{name: "LessThan", argLength: 1, reg: readflags},      // bool，true标志编码有符号x<y，否则为false。
		{name: "LessEqual", argLength: 1, reg: readflags},     // bool，true标志编码有符号x<=y否则为false。
		{name: "GreaterThan", argLength: 1, reg: readflags},   // bool，true标志编码有符号的x>y，否则为false。
		{name: "GreaterEqual", argLength: 1, reg: readflags},  // bool，true标志编码有符号x>=y，否则为false。
		{name: "LessThanU", argLength: 1, reg: readflags},     // bool，true标志编码无符号x<y，否则为false。
		{name: "LessEqualU", argLength: 1, reg: readflags},    // bool，true标志编码无符号x<=y，否则为false。
		{name: "GreaterThanU", argLength: 1, reg: readflags},  // bool，true标志编码无符号x>y，否则为false。
		{name: "GreaterEqualU", argLength: 1, reg: readflags}, // bool，true标志编码无符号x>=y，否则为false。

		// duffzero（必须是4字节对齐的）
		// arg0=内存地址为零（在R1中，更改为副作用）
		// arg1=要存储的值（始终为零）
		// arg2=mem 
		// auxint=偏移到duffzero代码以开始执行
		// 返回mem 
		{
			name:      "DUFFZERO",
			aux:       "Int64",
			argLength: 3,
			reg: regInfo{
				inputs:   []regMask{buildReg("R1"), buildReg("R0")},
				clobbers: buildReg("R1 R12 R14"), // R14是LR，R12是链接器蹦床暂存器
			},
			faultOnNilArg0: true,
		},

		// duffcopy（必须是4字节对齐的）
		// arg0=dst内存地址（在R2中，更改为副作用）
		// arg1=src内存地址（在R1中，更改为副作用）
		// auxint=偏移到duffcopy代码以开始执行
		// 返回mem 
		{
			name:      "DUFFCOPY",
			aux:       "Int64",
			argLength: 3,
			reg: regInfo{
				inputs:   []regMask{buildReg("R2"), buildReg("R1")},
				clobbers: buildReg("R0 R1 R2 R12 R14"), // R14是LR，R12是链接器蹦床暂存器
			},
			faultOnNilArg0: true,
			faultOnNilArg1: true,
		},

		// 大或未对齐的归零
		// arg0=内存地址为零（在R1中，更改为副作用）
		// arg1=最后一个元素的地址为零
		// arg2=要存储的值（始终为零）
		// 返回mem 
		// CMP R1，Rarg1 
		// BLE-2（PC）
		{
			name:      "LoweredZero",
			aux:       "Int64",
			argLength: 4,
			reg: regInfo{
				inputs:   []regMask{buildReg("R1"), gp, gp},
				clobbers: buildReg("R1"),
			},
			clobberFlags:   true,
			faultOnNilArg0: true,
		},

		// 大或未对齐移动
		// arg0=dst内存地址（在R2中，更改为副作用）
		// arg1=src内存地址（在R1中，更改为副作用）
		// arg2=src 
		// mem 
		// 返回mem 
		// MOVW。P4（R1），Rtmp 
		// MOVW。P Rtmp，4（R2）
		// CMP R1，Rarg2 
		// BLE-3（PC）
		{
			name:      "LoweredMove",
			aux:       "Int64",
			argLength: 4,
			reg: regInfo{
				inputs:   []regMask{buildReg("R2"), buildReg("R1"), gp},
				clobbers: buildReg("R1 R2"),
			},
			clobberFlags:   true,
			faultOnNilArg0: true,
			faultOnNilArg1: true,
		},

		// 调度程序确保仅在入口块中发生LoweredGetClosurePtr，
		// 并将其排序到块的最开头，以防止其他
		// 使用R7（arm.REGCTXT，闭包指针）
		{name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{buildReg("R7")}}, zeroWidth: true},

		// LoweredGetCallerSP返回当前函数调用方的SP。
		{name: "LoweredGetCallerSP", reg: gp01, rematerializeable: true},

		// LoweredGetCallerPC计算其“调用者”将返回的PC。
		// 也就是说，如果f调用g“调用”getcallerpc，
		// 结果应该是g将返回的f内的PC。
		// 请参阅运行时/stubs。进行更详细的讨论。
		{name: "LoweredGetCallerPC", reg: gp01, rematerializeable: true},

		// 这些函数有三个，因此它们可以有三个不同的寄存器输入。
		// 当我们检查0<=c<=cap（A），然后检查0<=b<=c（b），然后检查0<=A<=b（c）时，我们希望
		// 默认寄存器匹配，所以我们不需要不必要地复制寄存器。
		{name: "LoweredPanicBoundsA", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r2, r3}}, typ: "Mem", call: true}, // arg0=idx，arg1=len，arg2=mem，返回内存。AuxInt包含报告代码（参见genericOps.go中的PanicBounds）。
		{name: "LoweredPanicBoundsB", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r1, r2}}, typ: "Mem", call: true}, // arg0=idx，arg1=len，arg2=mem，返回内存。AuxInt包含报告代码（参见genericOps.go中的PanicBounds）。
		{name: "LoweredPanicBoundsC", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r0, r1}}, typ: "Mem", call: true}, // arg0=idx，arg1=len，arg2=mem，返回内存。AuxInt包含报告代码（参见genericOps.go中的PanicBounds）。
		// 扩展操作与边界操作相同，只是索引是64位的。
		{name: "LoweredPanicExtendA", argLength: 4, aux: "Int64", reg: regInfo{inputs: []regMask{r4, r2, r3}}, typ: "Mem", call: true}, // arg0=idxHi，arg1=idxLo，arg2=len，arg3=mem，返回内存。AuxInt包含报告代码（参见genericOps.go中的PanicExtend）。
		{name: "LoweredPanicExtendB", argLength: 4, aux: "Int64", reg: regInfo{inputs: []regMask{r4, r1, r2}}, typ: "Mem", call: true}, // arg0=idxHi，arg1=idxLo，arg2=len，arg3=mem，返回内存。AuxInt包含报告代码（参见genericOps.go中的PanicExtend）。
		{name: "LoweredPanicExtendC", argLength: 4, aux: "Int64", reg: regInfo{inputs: []regMask{r4, r0, r1}}, typ: "Mem", call: true}, // arg0=idxHi，arg1=idxLo，arg2=len，arg3=mem，返回内存。AuxInt包含报告代码（参见genericOps.go中的PanicExtend）。

		// 常量标志值。
		// 注意：浮点
		// 比较有一个“无序”的结果，但我们还没有使用这种野兽。
		// 此op供重写规则临时使用。它
		// 不能出现在生成的程序集中。
		{name: "FlagConstant", aux: "FlagConstant"},

		// （InvertFlags（CMP a b））==（CMP b a）
		// InvertFlags是一个伪操作，不能出现在程序集输出中。
		{name: "InvertFlags", argLength: 1}, // arg0的反向

		// LoweredWB调用运行时。gcWriteBarrier。arg0=destptr，arg1=srcptr，arg2=mem，aux=runtime。gcWriteBarrier 
		// 如果需要，它会保存所有GP寄存器，
		// 但会删除R14（LR），因为这是一个调用，而R12是链接器蹦床暂存器。
		{name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{buildReg("R2"), buildReg("R3")}, clobbers: (callerSave &^ gpg) | buildReg("R12 R14")}, clobberFlags: true, aux: "Sym", symEffect: "None"},
	}

	blocks := []blockData{
		{name: "EQ", controls: 1},
		{name: "NE", controls: 1},
		{name: "LT", controls: 1},
		{name: "LE", controls: 1},
		{name: "GT", controls: 1},
		{name: "GE", controls: 1},
		{name: "ULT", controls: 1},
		{name: "ULE", controls: 1},
		{name: "UGT", controls: 1},
		{name: "UGE", controls: 1},
		{name: "LTnoov", controls: 1}, // /'LT'但不尊重溢出
		{name: "LEnoov", controls: 1}, // /'LE'但不尊重溢出
		{name: "GTnoov", controls: 1}, // /'GT'但不尊重溢出
		{name: "GEnoov", controls: 1}, // /'GE'但不尊重溢出
	}

	archs = append(archs, arch{
		name:            "ARM",
		pkg:             "cmd/internal/obj/arm",
		genfile:         "../../arm/ssa.go",
		ops:             ops,
		blocks:          blocks,
		regnames:        regNamesARM,
		gpregmask:       gp,
		fpregmask:       fp,
		framepointerreg: -1, // /未使用
		linkreg:         int8(num["R14"]),
	})
}
